﻿using Grpc.Core;
using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Wen.GrpcService.Entity;
using Wen.GrpcService.InternalService;

namespace Wen.GrpcService.Services;

public class AuthService(ILogger<AuthService> logger, IFreeSql freeSql, UserService userService, IConfiguration _config) : Auther.AutherBase
{
    public override async Task<AuthReply> Auth(AuthRequest request, ServerCallContext context)
    {
        if (userService.VerifyLogin(request.Username, request.Password))
        {
            var roles = freeSql.Select<SysUserRole>().Where(a => a.UserName == request.Username)
                .ToList(a => a.RoleName);
            var tokenString = GenerateJwtToken(request.Username, roles);

            var claims = new List<Claim>
            {
                new(ClaimTypes.Name, request.Username)
            };

            var auth = new AuthReply()
            {
                Msg = "登录成功",
                Result = true,
                Token = tokenString,
            };
            auth.Roles.AddRange(roles);
            return auth;
        }

        return new AuthReply() { Msg = "获取用户信息失败，请检查输入的用户名和密码是否正确！", Result = false, Timeout = new Google.Protobuf.WellKnownTypes.Timestamp() };
    }

    private string GenerateJwtToken(string username, List<string> roles)
    {
        var claims = new List<Claim>
        {
            new(ClaimTypes.Name, username)
        };
        claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));

        var key = new SymmetricSecurityKey(
            Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"])
        );
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            issuer: _config["Jwt:Issuer"],
            audience: _config["Jwt:Audience"],
            claims: claims,
            expires: DateTime.Now.AddDays(7),
            signingCredentials: creds
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

